<template>
  <view class="drag-and-drop-sort-A" :style="{'width': containerSize.width, 'height': containerSize.height}">
    <view class="" :style="{'height': controlsList.length * 30.5 + 'vw'}"></view>
    <template v-if="controlsList.length !== 0">
      <view v-for="(item, index) in controlsList" :key="index" class="_item"
        :style="{
          'transition': curretnControlsIndex === index ? 'initial' : '.3s',
          'z-index': curretnControlsIndex === index ? 1 : 0,
          'width': '95vw',
          'height': '20vw',
          'top': controlsPositionArray[index].top + 'px',
          'left': 0 // 固定左边距
        }">
        <view @touchstart="handleTouchstart($event, index)" @touchmove="handleTouchmove" @touchend="handleTouchend" :style="{'background': item.color}" style="width: 100%; height: 20vw;">
          <slot name="content" :item="item"></slot>
        </view>
      </view>
    </template>
  </view>
</template>

<script>
export default {
  name: "drag-and-drop-sort-A",
  props: {
    // 容器大小
    containerSize: {
      type: Object,
      default: () => ({ width: '100%', height: '0' }),
    },
    // 控件的大小
    controlsSize: {
      type: Object,
      default: () => ({ width: '95vw', height: '20vw' }),
    },
    // 数据列表
    controlsList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      // 控件的间距
      margin: {
        margin_x: 0, // 不需要水平间距
        margin_y: 5, // 垂直间距
      },
      // 记录所有控件的初始位置
      recordInitControlsPoisitonList: [],
      // 控件的位置
      controlsPositionArray: [],
      // 记录当前手指的位置
      recordPosition: {
        x: 0,
        y: 0,
      },
      // 记录当前操作的控件数据
      recordControlsPositionItem: {},
      // 当前操作的控件的下标
      curretnControlsIndex: -1,
      // 是否在移动中
      isMobile: false,
    };
  },
  watch: {
    controlsList: {
      handler(newVal) {
        this.controlsPositionArray = this.initControlsPosition(newVal);
      },
      deep: true,
      immediate: true,
    }
  },
  methods: {
    /** 初始化各个控件的位置 */
    initControlsPosition(controlsList) {
      let tempArray = [];
      let cumulativeTop = this.margin.margin_y; // 初始化累计高度

      // 设置控件位置
      for (let i = 0; i < controlsList.length; i++) {
        tempArray[i] = {
          left: 0, // 每个控件都在最左边
          top: cumulativeTop,
        };

        // 更新累计高度
        cumulativeTop += this.controlsSize.height + this.margin.margin_y;
        if (i >= 0) {
          cumulativeTop += 40; // 对于第二个及以后的控件增加额外的 40px
        }
      }

      // 记录数据 - 进行深拷贝
      this.recordInitControlsPoisitonList = [...tempArray];
      // 返回数据
      return tempArray;
    },

    /** 处理手指触摸后移动 */
    handleTouchmove(event) {
      const touch = event.touches[0];
      const pageY = touch.pageY;

      // 如果是第一个控件或最后一个控件，不允许拖动
      if (this.curretnControlsIndex === 0 || this.curretnControlsIndex === this.controlsList.length - 1) {
        return;
      }

      if (this.curretnControlsIndex !== -1) {
        // 获取移动的差
        const newTop = this.controlsPositionArray[this.curretnControlsIndex].top + (pageY - this.recordPosition.y);
        this.$set(this.controlsPositionArray, this.curretnControlsIndex, { top: newTop });

        // 记录位置
        this.recordPosition = { x: 0, y: pageY };

        // 判断当前移动的位置是否需要进行排序
        if (this.curretnControlsIndex + 1 < this.controlsList.length && newTop + this.controlsSize.height > this.recordInitControlsPoisitonList[this.curretnControlsIndex + 1].top + this.margin.margin_y + this.controlsSize.height / 2) {
          this._handleChangeControlsPosition(this.curretnControlsIndex + 1);
        } else if (this.curretnControlsIndex > 0 && newTop < this.recordInitControlsPoisitonList[this.curretnControlsIndex - 1].top + this.margin.margin_y + this.controlsSize.height / 2) {
          this._handleChangeControlsPosition(this.curretnControlsIndex - 1);
        }
      }
    },

    /** 处理手指触摸开始事件 */
    handleTouchstart(event, index) {
      const touch = event.touches[0];
      const pageY = touch.pageY;

      // 记录一些数据
      this.curretnControlsIndex = index;
      this.recordPosition = { x: 0, y: pageY };
      this.recordControlsPositionItem = this.controlsPositionArray[index];
    },

    /** 处理手指松开事件 */
    handleTouchend(event) {
      // 将操控的控件归位
      this.controlsPositionArray[this.curretnControlsIndex] = this.recordInitControlsPoisitonList[this.curretnControlsIndex];
      this.curretnControlsIndex = -1;
    },

    /**
     * 处理交换控件位置的方法 - 
     * @param {number} index 需要与第几个下标交换位置
     * */
    _handleChangeControlsPosition(index) {
      // 判断是否在交换中
      if (this.isMobile) {
        return;
      }
      this.isMobile = true;

      // 确保第一个和最后一个控件不与其他控件交换位置
      if (this.curretnControlsIndex === 0 || this.curretnControlsIndex === this.controlsList.length - 1 || index === 0 || index === this.controlsList.length - 1) {
        this.isMobile = false;
        return;
      }

      // 记录当前操控的控件数据
      let tempControls = this.controlsList[this.curretnControlsIndex];
      // 交换位置
      this.controlsList[this.curretnControlsIndex] = this.controlsList[index];
      this.controlsList[index] = tempControls;

      // 调整控件位置数据
      this.controlsPositionArray[index] = this.controlsPositionArray[this.curretnControlsIndex];
      this.controlsPositionArray[this.curretnControlsIndex] = this.recordControlsPositionItem;

      // 改变当前选中的位置
      this.curretnControlsIndex = index;

      // 记录新位置的数据
      this.recordControlsPositionItem = this.recordInitControlsPoisitonList[this.curretnControlsIndex];

      // 重新编号
      this.controlsList.forEach((item, idx) => {
        if (item.Day) {
          item.Day = String(idx);
        }
      });

      // 触发自定义事件，将新的 controlsList 传递给父组件
      this.$emit('update:controlsArray', this.controlsList);

      // 交换结束
      this.isMobile = false;
    }
  }
}
</script>

<style scoped lang="scss">
.drag-and-drop-sort-A {
  position: relative;
  width: 100%;
  height: 100%;
}

._item {
  position: absolute;
  width: 95vw;
  height: 20vw;
  box-sizing: border-box; // 确保内边距和边框包含在宽度内
}
</style>